home *** CD-ROM | disk | FTP | other *** search
/ PD Collection CD 1 / PD Collection CD 1.iso / textual / pdftops / xpdf / c++ / PSOutput < prev    next >
Encoding:
Text File  |  1996-06-08  |  16.3 KB  |  629 lines

  1. //========================================================================
  2. //
  3. // PSOutput.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. //#pragma implementation
  11. #endif
  12.  
  13. #include <stddef.h>
  14. #include <stdarg.h>
  15. #include "GString.h"
  16. #include "config.h"
  17. #include "Error.h"
  18. #include "GfxFont.h"
  19. #include "Catalog.h"
  20. #include "Page.h"
  21. #include "PSOutput.h"
  22.  
  23. //------------------------------------------------------------------------
  24. // PostScript prolog and setup
  25. //------------------------------------------------------------------------
  26.  
  27. #define psMaxFonts 100
  28.  
  29. static char *prolog[] = {
  30.   "%%BeginProlog",
  31.   "% PDF special state",
  32.   "/pdfDictSize 14 def",
  33.   "/pdfStartPage {",
  34.   "  pdfDictSize dict begin",
  35.   "  /pdfFill [0] def",
  36.   "  /pdfStroke [0] def",
  37.   "  /pdfLastFill false def",
  38.   "  /pdfLastStroke false def",
  39.   "  /pdfTextMat [1 0 0 1 0 0] def",
  40.   "  /pdfFontSize 0 def",
  41.   "  /pdfCharSpacing 0 def",
  42.   "  /pdfTextLeading 0 def",
  43.   "  /pdfTextRender 0 def",
  44.   "  /pdfTextRise 0 def",
  45.   "  /pdfWordSpacing 0 def",
  46.   "  /pdfHorizScaling 100 def",
  47.   "  /pdfLineX 0 def",
  48.   "  /pdfLineY 0 def",
  49.   "} def",
  50.   "/pdfEndPage { end } def",
  51.   "/sCol { pdfLastStroke not {",
  52.   "          pdfStroke aload length",
  53.   "          dup 1 eq { pop setgray }",
  54.   "          { 3 eq { setrgbcolor } { setcmykcolor} ifelse } ifelse",
  55.   "          /pdfLastStroke true def /pdfLastFill false def",
  56.   "        } if } def",
  57.   "/fCol { pdfLastFill not {",
  58.   "          pdfFill aload length",
  59.   "          dup 1 eq { pop setgray }",
  60.   "          { 3 eq { setrgbcolor } { setcmykcolor} ifelse } ifelse",
  61.   "          /pdfLastFill true def /pdfLastStroke false def",
  62.   "        } if } def",
  63.   "% build a font",
  64.   "/pdfMakeFont {",
  65.   "  3 2 roll findfont",
  66.   "  3 2 roll 1 matrix scale makefont",
  67.   "  dup length dict begin",
  68.   "    { 1 index /FID ne { def } { pop pop } ifelse } forall",
  69.   "    /Encoding exch def",
  70.   "    currentdict",
  71.   "  end",
  72.   "  definefont pop",
  73.   "} def",
  74.   "% graphics state operators",
  75.   "/q { gsave pdfDictSize dict begin } def",
  76.   "/Q { end grestore } def",
  77.   "/cm { concat } def",
  78.   "/d { setdash } def",
  79.   "/i { setflat } def",
  80.   "/j { setlinejoin } def",
  81.   "/J { setlinecap } def",
  82.   "/M { setmiterlimit } def",
  83.   "/w { setlinewidth } def",
  84.   "% color operators",
  85.   "/g { dup 1 array astore /pdfFill exch def setgray",
  86.   "    /pdfLastFill true def /pdfLastStroke false def } def",
  87.   "/G { dup 1 array astore /pdfStroke exch def setgray",
  88.   "     /pdfLastStroke true def /pdfLastFill false def } def",
  89.   "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
  90.   "     /pdfLastFill true def /pdfLastStroke false def } def",
  91.   "/K { 4 copy 4 array astore /pdfStroke exch def setcmykcolor",
  92.   "     /pdfLastStroke true def /pdfLastFill false def } def",
  93.   "/rg { 3 copy 3 array astore /pdfFill exch def setrgbcolor",
  94.   "     /pdfLastFill true def /pdfLastStroke false def } def",
  95.   "/RG { 3 copy 3 array astore /pdfStroke exch def setrgbcolor",
  96.   "     /pdfLastStroke true def /pdfLastFill false def } def",
  97.   "% path segment operators",
  98.   "/m { moveto } def",
  99.   "/l { lineto } def",
  100.   "/c { curveto } def",
  101.   "/v { currentpoint 6 2 roll curveto } def",
  102.   "/y { 2 copy curveto } def",
  103.   "/re { 4 2 roll moveto 1 index 0 rlineto 0 1 index rlineto",
  104.   "      exch neg 0 rlineto neg 0 exch rlineto } def",
  105.   "/h { closepath } def",
  106.   "% path painting operators",
  107.   "/n { newpath } def",
  108.   "/S { sCol stroke } def",
  109.   "/s { closepath sCol stroke } def",
  110.   "/f { fCol fill } def",
  111.   "/f* { fCol eofill } def",
  112.   "/B { fCol gsave fill grestore sCol stroke } def",
  113.   "/b { closepath fCol gsave fill grestore sCol stroke } def",
  114.   "/B* { fCol gsave eofill grestore sCol stroke } def",
  115.   "/b* { closepath fCol gsave eofill grestore sCol stroke } def",
  116.   "% text state operators",
  117.   "/Tc { /pdfCharSpacing exch def } def",
  118.   "/Tf { dup /pdfFontSize exch def",
  119.   "      dup pdfHorizScaling 100 div mul exch matrix scale",
  120.   "      pdfTextMat matrix concatmatrix dup 4 0 put dup 5 0 put",
  121.   "      exch findfont exch makefont setfont } def",
  122.   "/TL { /pdfTextLeading exch def } def",
  123.   "/Tr { /pdfTextRender exch def } def",
  124.   "/Ts { /pdfTextRise exch def } def",
  125.   "/Tw { /pdfWordSpacing exch def } def",
  126.   "/Tz { /pdfHorizScaling exch def } def",
  127.   "% text positioning operators",
  128.   "/Td { pdfLineY add /pdfLineY exch def",
  129.   "      pdfLineX add /pdfLineX exch def",
  130.   "      pdfLineX pdfLineY pdfTextMat transform moveto} def",
  131.   "/TD { dup neg /pdfTextLeading exch def Td } def",
  132.   "/Tm { /pdfTextMat exch def",
  133.   "      /pdfLineX 0 def /pdfLineY 0 def",
  134.   "      0 0 pdfTextMat transform moveto } def",
  135.   "/T* { /pdfLineY pdfLineY pdfTextLeading sub def",
  136.   "      pdfLineX pdfLineY pdfTextMat transform moveto } def",
  137.   "% text string operators",
  138.   "/Tj { pdfTextRender 1 and 0 eq { fCol } { sCol } ifelse",
  139.   "      0 pdfTextRise pdfTextMat dtransform rmoveto",
  140.   "      pdfFontSize mul",
  141.   "      1 index stringwidth pdfTextMat idtransform pop",
  142.   "      sub 1 index length div",
  143.   "      pdfWordSpacing 0 pdfTextMat dtransform 32",
  144.   "      4 3 roll pdfCharSpacing add 0 pdfTextMat dtransform",
  145.   "      6 5 roll awidthshow",
  146.   "      0 pdfTextRise neg pdfTextMat dtransform rmoveto } def",
  147.   "/TJm { pdfFontSize 0.001 mul mul neg 0",
  148.   "       pdfTextMat dtransform rmoveto } def",
  149.   "%%EndProlog",
  150.   NULL
  151. };
  152.  
  153. //------------------------------------------------------------------------
  154. // Fonts
  155. //------------------------------------------------------------------------
  156.  
  157. struct PSFont {
  158.   char *name;            // PDF name
  159.   char *psName;            // PostScript name
  160. };
  161.  
  162. struct PSSubstFont {
  163.   char *psName;            // PostScript name
  164.   double mWidth;        // width of 'm' character
  165. };
  166.  
  167. static PSFont psFonts[] = {
  168.   {"Courier",               "Courier"},
  169.   {"Courier-Bold",          "Courier-Bold"},
  170.   {"Courier-Oblique",       "Courier-Bold"},
  171.   {"Courier-BoldOblique",   "Courier-BoldOblique"},
  172.   {"Helvetica",             "Helvetica"},
  173.   {"Helvetica-Bold",        "Helvetica-Bold"},
  174.   {"Helvetica-Oblique",     "Helvetica-Oblique"},
  175.   {"Helvetica-BoldOblique", "Helvetica-BoldOblique"},
  176.   {"Symbol",                "Symbol"},
  177.   {"Times-Roman",           "Times-Roman"},
  178.   {"Times-Bold",            "Times-Bold"},
  179.   {"Times-Italic",          "Times-Italic"},
  180.   {"Times-BoldItalic",      "Times-BoldItalic"},
  181.   {"ZapfDingbats",          "ZapfDingbats"},
  182.   {NULL}
  183. };
  184.  
  185. static PSSubstFont psSubstFonts[] = {
  186.   {"Helvetica",             0.833},
  187.   {"Helvetica-Oblique",     0.833},
  188.   {"Helvetica-Bold",        0.889},
  189.   {"Helvetica-BoldOblique", 0.889},
  190.   {"Times-Roman",           0.788},
  191.   {"Times-Italic",          0.722},
  192.   {"Times-Bold",            0.833},
  193.   {"Times-BoldItalic",      0.778},
  194.   {"Courier",               0.600},
  195.   {"Courier-Oblique",       0.600},
  196.   {"Courier-Bold",          0.600},
  197.   {"Courier-BoldOblique",   0.600}
  198. };
  199.  
  200. //------------------------------------------------------------------------
  201. // PSOutput
  202. //------------------------------------------------------------------------
  203.  
  204. PSOutput::PSOutput(char *fileName, Catalog *catalog,
  205.            int firstPage, int lastPage) {
  206.   Dict *fontDict;
  207.   GfxFontDict *gfxFontDict;
  208.   GfxFont *font;
  209.   GString *tags[psMaxFonts];
  210.   char **p;
  211.   int pg, i, j, k;
  212.  
  213.   // open file
  214.   ok = gTrue;
  215.   if (!(f = fopen(fileName, "w"))) {
  216.     error(0, "Couldn't open PostScript file '%s'", fileName);
  217.     ok = gFalse;
  218.     return;
  219.   }
  220.  
  221.   // write header
  222.   writePS("%%!PS-Adobe-3.0\n");
  223.   writePS("%%%%Creator: xpdf %s\n", xpdfVersion);
  224.   writePS("%%%%Pages: %d\n", lastPage - firstPage + 1);
  225.   writePS("%%%%EndComments\n");
  226.  
  227.   // write prolog
  228.   for (p = prolog; *p; ++p)
  229.     writePS("%s\n", *p);
  230.  
  231.   // write document setup
  232.   writePS("%%%%BeginSetup\n");
  233.   j = 0;
  234.   for (pg = firstPage; pg <= lastPage; ++pg) {
  235.     fontDict = catalog->getPage(pg)->getFontDict();
  236.     if (fontDict) {
  237.       gfxFontDict = new GfxFontDict(fontDict);
  238.       for (i = 0; i < gfxFontDict->getNumFonts(); ++i) {
  239.     font = gfxFontDict->getFont(i);
  240.     for (k = 0; k < j; ++k) {
  241.       if (tags[k]->cmp(font->getTag()) == 0)
  242.         break;
  243.     }
  244.     if (k >= j) {
  245.       if (j < psMaxFonts) {
  246.         tags[j++] = font->getTag()->copy();
  247.         setupFont(font);
  248.       } else {
  249.         error(0, "Too many fonts in PostScript output");
  250.         ok = gFalse;
  251.         return;
  252.       }
  253.     }
  254.       }
  255.       delete gfxFontDict;
  256.     }
  257.   }
  258.   for (k = 0; k < j; ++k)
  259.     delete tags[k];
  260.   writePS("%%%%EndSetup\n");
  261.  
  262.   // initialize sequential page number
  263.   seqPage = 1;
  264. }
  265.  
  266. PSOutput::~PSOutput() {
  267.   if (f)
  268.     fclose(f);
  269. }
  270.  
  271. void PSOutput::setupFont(GfxFont *font) {
  272.   GString *name;
  273.   char *psName;
  274.   double scale;
  275.   int i;
  276.  
  277.   name = font->getName();
  278.   psName = NULL;
  279.   scale = 1.0;
  280.   if (name) {
  281.     for (i = 0; psFonts[i].name; ++i) {
  282.       if (name->cmp(psFonts[i].name) == 0) {
  283.     psName = psFonts[i].psName;
  284.     break;
  285.       }
  286.     }
  287.   }
  288.   if (!psName) {
  289.     if (font->isFixedWidth())
  290.       i = 8;
  291.     else if (font->isSerif())
  292.       i = 4;
  293.     else
  294.       i = 0;
  295.     if (font->isBold())
  296.       i += 2;
  297.     if (font->isItalic())
  298.       i += 1;
  299.     psName = psSubstFonts[i].psName;
  300.     scale = font->getWidth('m') / psSubstFonts[i].mWidth;
  301.     if (scale < 0.1)
  302.       scale = 1;
  303.   }
  304.  
  305.   writePS("/%s /%s %g\n", font->getTag()->getCString(), psName, scale);
  306.   for (i = 0; i < 256; ++i)
  307.     writePS("%s/%s\n", (i == 0) ? "[ " : "  ", font->getCharName(i));
  308.   writePS("]\n");
  309.   writePS("pdfMakeFont\n");
  310. }
  311.  
  312. void PSOutput::startPage(int pageNum, int x1, int y1, int x2, int y2) {
  313.   int width, height, t;
  314.   double xScale, yScale;
  315.  
  316.   writePS("%%%%Page: %d %d\n", pageNum, seqPage);
  317.   writePS("%%%%BeginPageSetup\n");
  318.   writePS("pdfStartPage\n");
  319.  
  320.   // rotate, translate, and scale page
  321.   width = x2 - x1;
  322.   height = y2 - y1;
  323.   if (width > height) {
  324.     writePS("90 rotate\n");
  325.     writePS("%d %d translate\n", -x1, -(y1 + paperWidth));
  326.     t = width;
  327.     width = height;
  328.     height = t;
  329.   } else {
  330.     if (x1 != 0 || y1 != 0)
  331.       writePS("%d %d translate\n", -x1, -y1);
  332.   }
  333.   if (width > paperWidth || height > paperHeight) {
  334.     xScale = (double)paperWidth / (double)width;
  335.     yScale = (double)paperHeight / (double)height;
  336.     if (yScale < xScale)
  337.       xScale = yScale;
  338.     writePS("%0.4f %0.4f scale\n", xScale, xScale);
  339.   }
  340.  
  341.   writePS("%%%%EndPageSetup\n");
  342.   ++seqPage;
  343. }
  344.  
  345. void PSOutput::endPage() {
  346.   writePS("showpage\n");
  347.   writePS("%%%%PageTrailer\n");
  348.   writePS("pdfEndPage\n");
  349. }
  350.  
  351. void PSOutput::trailer() {
  352.   writePS("%%%%Trailer\n");
  353.   writePS("%%%%EOF\n");
  354. }
  355.  
  356. void PSOutput::writePS(char *fmt, ...) {
  357.   va_list args;
  358.  
  359.   va_start(args, fmt);
  360.   vfprintf(f, fmt, args);
  361.   va_end(args);
  362. }
  363.  
  364. void PSOutput::writePSString(GString *s) {
  365.   Guchar *p;
  366.   int n;
  367.  
  368.   fputc('(', f);
  369.   for (p = (Guchar *)s->getCString(), n = s->getLength(); n; ++p, --n) {
  370.     if (*p == '(' || *p == ')')
  371.       fprintf(f, "\\%c", *p);
  372.     else if (*p < 0x20 || *p >= 0x80)
  373.       fprintf(f, "\\%03o", *p);
  374.     else
  375.       fputc(*p, f);
  376.   }
  377.   fputc(')', f);
  378. }
  379.  
  380. void PSOutput::writeStream(Stream *str, GBool inlineImg, GBool needA85) {
  381.   int c1, c2, c3;
  382.   int a85[5];
  383.   Gulong t;
  384.   int n, m, i;
  385.  
  386.   // back to start of stream
  387.   str->reset();
  388.  
  389.   // for inline image: need to read three chars ahead to check for
  390.   // 'EI' tag
  391.   if (inlineImg) {
  392.     c1 = str->getChar();
  393.     c2 = str->getChar();
  394.   } else {
  395.     c1 = c2 = '\0';
  396.   }
  397.  
  398.   // do ASCII85 re-encoded stream
  399.   if (needA85) {
  400.     m = 0;
  401.     do {
  402.       t = 0;
  403.       for (n = 0; n < 4; ++n) {
  404.     if (inlineImg) {
  405.       c3 = str->getChar();
  406.       if ((c1 == '\n' || c1 == '\r') && c2 == 'E' && c3 == 'I')
  407.         break;
  408.       t = (t << 8) + c1;
  409.       c1 = c2;
  410.       c2 = c3;
  411.     } else {
  412.       if ((c1 = str->getChar()) == EOF)
  413.         break;
  414.       t = (t << 8) + c1;
  415.     }
  416.       }
  417.       if (n > 0) {
  418.     if (n == 4 && t == 0) {
  419.       fputc('z', f);
  420.       if (++m == 65) {
  421.         fputc('\n', f);
  422.         m = 0;
  423.       }
  424.     } else {
  425.       if (n < 4)
  426.         t <<= 8 * (4 - n);
  427.       for (i = 4; i >= 0; --i) {
  428.         a85[i] = t % 85;
  429.         t /= 85;
  430.       }
  431.       for (i = 0; i <= n; ++i) {
  432.         fputc((char)(a85[i] + 0x21), f);
  433.         if (++m == 65) {
  434.           fputc('\n', f);
  435.           m = 0;
  436.         }
  437.       }
  438.     }
  439.       }
  440.     } while (n == 4);
  441.     fputc('~', f);
  442.     if (++m == 65)
  443.       fputc('\n', f);
  444.     fputc('>', f);
  445.  
  446.   // stream is already ASCII, just copy it
  447.   } else {
  448.     while (1) {
  449.       if (inlineImg) {
  450.     c3 = str->getChar();
  451.     if ((c1 == '\n' || c1 == '\r') && c2 == 'E' && c3 == 'I')
  452.       break;
  453.       } else {
  454.     if ((c1 = str->getChar()) == EOF)
  455.       break;
  456.       }
  457.       fputc(c1, f);
  458.     }
  459.   }
  460.  
  461.   // add a newline to the end
  462.   fputc('\n', f);
  463. }
  464.  
  465. void PSOutput::writeImage(Dict *dict, Stream *str, GBool inlineImg) {
  466.   GBool mask, indexed;
  467.   Object obj1, obj2;
  468.   char *s;
  469.   GString *s1;
  470.   int numComps, w, h, bits;
  471.   int c;
  472.   int n, i;
  473.  
  474.   // image or image mask?
  475.   dict->lookup("ImageMask", &obj1);
  476.   if (obj1.isNull()) {
  477.     obj1.free();
  478.     dict->lookup("IM", &obj1);
  479.   }
  480.   mask = gFalse;
  481.   if (obj1.isBool())
  482.     mask = obj1.getBool();
  483.   obj1.free();
  484.  
  485.   // color space
  486.   numComps = 1;
  487.   indexed = gFalse;
  488.   if (!mask) {
  489.     if (dict->lookup("ColorSpace", &obj1)->isNull()) {
  490.       obj1.free();
  491.       dict->lookup("CS", &obj1);
  492.     }
  493.     numComps = 1;
  494.     if (obj1.isName("DeviceGray") || obj1.isName("G")) {
  495.       writePS("/DeviceGray setcolorspace\n");
  496.       numComps = 1;
  497.     } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) {
  498.       writePS("/DeviceRGB setcolorspace\n");
  499.       numComps = 3;
  500.     } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) {
  501.       writePS("/DeviceCMYK setcolorspace\n");
  502.       numComps = 4;
  503.     } else if (obj1.isArray()) {
  504.       obj1.arrayGet(0, &obj2);
  505.       if (obj2.isName("DeviceGray") || obj2.isName("G")) {
  506.     writePS("/DeviceGray setcolorspace\n");
  507.     numComps = 1;
  508.       } else if (obj2.isName("DeviceRGB") || obj2.isName("RGB")) {
  509.     writePS("/DeviceRGB setcolorspace\n");
  510.     numComps = 3;
  511.       } else if (obj2.isName("DeviceCMYK") || obj2.isName("CMYK")) {
  512.     writePS("/DeviceCMYK setcolorspace\n");
  513.     numComps = 4;
  514.       } else if (obj2.isName("Indexed") || obj2.isName("I")) {
  515.     indexed = gTrue;
  516.     numComps = 1;
  517.     obj2.free();
  518.     obj1.arrayGet(1, &obj2);
  519.     n = 1;
  520.     if (obj2.isName("DeviceGray") || obj2.isName("G")) {
  521.       writePS("[/Indexed /DeviceGray");
  522.       n = 1;
  523.     } else if (obj2.isName("DeviceRGB") || obj2.isName("RGB")) {
  524.       writePS("[/Indexed /DeviceRGB");
  525.       n = 3;
  526.     } else if (obj2.isName("DeviceCMYK") || obj2.isName("CMYK")) {
  527.       writePS("[/Indexed /DeviceCMYK");
  528.       n = 4;
  529.     }
  530.     obj2.free();
  531.     if (obj1.arrayGet(2, &obj2)->isInt()) {
  532.       writePS(" %d\n", obj2.getInt());
  533.       n *= (1 + obj2.getInt());
  534.     }
  535.     obj2.free();
  536.     obj1.arrayGet(3, &obj2);
  537.     writePS("<");
  538.     if (obj2.isStream()) {
  539.       obj2.streamReset();
  540.       for (i = 0; i < n; ++i) {
  541.         if ((c = obj2.streamGetChar()) == EOF)
  542.           writePS("00");
  543.         else
  544.           writePS("%02x", c);
  545.       }
  546.     } else if (obj2.isString()) {
  547.       s = obj2.getString()->getCString();
  548.       for (i = 0; i < n; ++i)
  549.         writePS("%02x", *s++ & 0xff);
  550.     }
  551.     writePS(">\n] setcolorspace\n");
  552.       }
  553.       obj2.free();
  554.     }
  555.     obj1.free();
  556.   }
  557.  
  558.   // image dictionary
  559.   writePS("<<\n  /ImageType 1\n");
  560.  
  561.   // width, height, matrix, bits per component
  562.   if (dict->lookup("Width", &obj1)->isNull()) {
  563.     obj1.free();
  564.     dict->lookup("W", &obj1);
  565.   }
  566.   if (obj1.isInt())
  567.     writePS("  /Width %d\n", w = obj1.getInt());
  568.   else
  569.     w = 0;
  570.   obj1.free();
  571.   if (dict->lookup("Height", &obj1)->isNull()) {
  572.     obj1.free();
  573.     dict->lookup("H", &obj1);
  574.   }
  575.   if (obj1.isInt())
  576.     writePS("  /Height %d\n", h = obj1.getInt());
  577.   else
  578.     h = 0;
  579.   obj1.free();
  580.   writePS("  /ImageMatrix [%d 0 0 %d 0 %d]\n", w, -h, h);
  581.   if (dict->lookup("BitsPerComponent", &obj1)->isNull()) {
  582.     obj1.free();
  583.     dict->lookup("BPC", &obj1);
  584.   }
  585.   bits = 0;
  586.   if (obj1.isInt())
  587.     writePS("  /BitsPerComponent %d\n", bits = obj1.getInt());
  588.   obj1.free();
  589.  
  590.   // decode 
  591.   if (dict->lookup("Decode", &obj1)->isNull()) {
  592.     obj1.free();
  593.     dict->lookup("D", &obj1);
  594.   }
  595.   writePS("  /Decode [");
  596.   if (obj1.isArray()) {
  597.     n = obj1.arrayGetLength();
  598.     for (i = 0; i < n; ++i) {
  599.       if (obj1.arrayGet(i, &obj2)->isNum())
  600.     writePS("%g%s", obj2.getNum(), i < n-1 ? " " : "");
  601.       obj2.free();
  602.     }
  603.   } else {
  604.     if (indexed) {
  605.       writePS("0 %d", (1 << bits) - 1);
  606.     } else {
  607.       for (i = 0; i < numComps; ++i)
  608.     writePS("0 1%s", i < numComps-1 ? " " : "");
  609.     }
  610.   }
  611.   writePS("]\n");
  612.   obj1.free();
  613.  
  614.   // data source
  615.   writePS("  /DataSource currentfile\n");
  616.   if (str->isBinary())
  617.     writePS("    /ASCII85Decode filter\n");
  618.   s1 = str->getPSFilter("    ");
  619.   writePS("%s", s1->getCString());
  620.   delete s1;
  621.  
  622.   // end of image dictionary
  623.   writePS(">>\n%s\n", mask ? "imagemask" : "image");
  624.  
  625.   // image data
  626.   writeStream(str->getBaseStream(), inlineImg, str->isBinary());
  627. }
  628.  
  629.